/*
 * FunctionDefinitionNode.cpp
 *
 *  Created on: 21/nov/2010
 *      Author: computer
 */

#include "DerivationTree.h"
#include "Lambda.h"
#include "FunctionDefinitionInstruction.h"

FunctionDefinitionNode::FunctionDefinitionNode() : NodeTree_CRTP<FunctionDefinitionNode>() { }

FunctionDefinitionNode::FunctionDefinitionNode(const FunctionDefinitionNode& copy) : NodeTree_CRTP<FunctionDefinitionNode>(copy), name(copy.name), listInstruction(copy.listInstruction), listParameter(copy.listParameter) { }

void FunctionDefinitionNode::setName(const AutoPointer<NodeTree>& _name) {
	name = _name;
}

void FunctionDefinitionNode::addInstruction(const AutoPointer<NodeTree>& instruction) {
	listInstruction.push_back(instruction);
}

void FunctionDefinitionNode::addParameter(const AutoPointer<NodeTree>& parameter) {
	listParameter.push_back(parameter);
}

bool FunctionDefinitionNode::execute(Pointer<LeonardVirtualMachine> LVM) {
	name->execute(LVM);
	std::list< AutoPointer<NodeTree> >::reverse_iterator i;
	for (i = listParameter.rbegin(); i != listParameter.rend(); ++i) {
		(*i)->execute(LVM);//TODO TODO
		//LVM->pop(); //TODO really the parameter doesn't load nothing into the stack?
	}
	AutoPointer<TreeExpression::Expression> functionDefinition = LVM->top();
	LVM->pop();
	TreeExpression::FunctionDefinitionInstruction* fd = dynamic_cast<TreeExpression::FunctionDefinitionInstruction*>(functionDefinition.get());
	while (!LVM->emptyPattern()) {
		fd->addParameter(LVM->topPattern());
		LVM->popPattern();
	}
	TreeExpression::Lambda* ris = new TreeExpression::Lambda(fd->getName());
	std::list< AutoPointer<NodeTree> >::reverse_iterator j;
	for (j = listInstruction.rbegin(); j != listInstruction.rend(); ++j) {
		(*j)->execute(LVM);
		ris->addInstruction(LVM->top());
		LVM->pop();
	}
	ris->setPattern(fd->getParameter());//set the parameter
	AutoPointer<TreeExpression::Expression> lambda(ris);
	fd->setSon(lambda);
	LVM->push(functionDefinition);//TODO sf
	return true;
}
